package com.cc.config.security;

/**
 * @ClassName: JwtAuthenticationTokenFilter
 * @Description: jwt过滤器
 * @Author: 晓东√
 * @Date: 2024-12-19 14:19
 * @Version: 1.0
 **/

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cc.comm.util.JwtTokenUtil;
import com.cc.config.JwtProperties;
import com.cc.entity.Employees;
import com.cc.entity.LoginUser;
import com.cc.mapper.EmployeesMapper;
import com.cc.service.RedisService;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Objects;

/**
 * 自定义一个过滤器，这个过滤器会去获取请求头中的token，对token进行解析取出其中的userName。
 * 使用userName去redis中获取对应的LoginUser对象。
 * 然后封装Authentication对象存入SecurityContextHolder。
 * SpringSecurity后面执行的过滤器会去SecurityContextHolder中获取信息，
 * 所以在放行之前要将信息存入SecurityContextHolder。
 */
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    @Autowired
    JwtProperties jwtProperties;
    @Autowired
    JwtTokenUtil jwtTokenUtil;

    @Autowired
    EmployeesMapper employeesMapper;

    @Autowired
    RedisService redisService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 从请求头中提取 JWT 令牌
        String token = request.getHeader(jwtProperties.getTokenHeader());

        //如果没有token
        if (!StringUtils.hasText(token)) {
            //放行
            filterChain.doFilter(request, response);
            return;
        }
       /* //去掉 "Bearer " 前缀
        String jwt = token.substring(7);*/
        String userName;
        try {
            userName = jwtTokenUtil.getUserNameFromToken(token);
        } catch (Exception e) {
            throw new RuntimeException("token非法");
        }
        //通过数据库查询用户信息及用户权限
        // 查询
        /*LambdaQueryWrapper<Employees> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Employees::getLoginName, userName);
        Employees employees = employeesMapper.selectOne(queryWrapper);
        if (Objects.isNull(employees)) {
            throw new RuntimeException("用户未登录");
        }*/
        //从redis中获取用户信息
        String redisKey = "loginUser:" + userName;
        LoginUser loginUser = (LoginUser) redisService.get(redisKey);
        if (Objects.isNull(loginUser)) {
            throw new RuntimeException("用户未登录");
        }

        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());

        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        //放行
        filterChain.doFilter(request, response);
        //将该过滤器放在UsernamePasswordAuthenticationFilter过滤器之前
        //在security配置类中配置


    }
}
